package com.googlecode.ebasys.web.controller;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;

import com.googlecode.ebasys.web.ViewConfiguration;

/**
 * Base Spring MVC Controller for EBASYS modules
 * 
 * Offers composite view by dividing main template into three generic parts:
 * layout (main frame), navigation and content frames. Example template could
 * look like this:
 * <pre>
 * +---------------layout-+
 * |+-nav-+ +----content-+|  
 * ||     | |            ||
 * ||     | |            ||
 * |+-----+ +------------+|
 * +----------------------+
 * </pre>
 * You should inject the parts with help of spring context.
 * 
 * @author Tomas Varaneckas
 * @version $Id: BaseController.java 34 2009-01-12 18:17:21Z tomas.varaneckas $
 * @see ViewConfiguration
 */
public abstract class BaseController extends AbstractController {

    /**
     * View configuration object
     */
    private ViewConfiguration view;

    /**
     * Sets view configuration
     * @param view
     */
    public void setView(final ViewConfiguration view) {
        this.view = view;
    }

    @Override
    protected void initApplicationContext() {
        if (this.view == null) {
            throw new IllegalArgumentException("Property 'view' is required");
        }
    }

    @Override
    protected ModelAndView handleRequestInternal(
            final HttpServletRequest request, final HttpServletResponse response)
            throws Exception {
        final Map<String, Object> model = new HashMap<String, Object>();
        model.put("view", view);
        final ModelAndView mav = new ModelAndView(view.getLayout(), model);
        handleRequest(mav, request, response);
        return mav;
    }

    /**
     * Main concrete controller method which should do the work
     * 
     * The implemented method should use the provided instance of
     * {@link ModelAndView} to set the output variables. The instance already
     * contains the configured layout template name. In addition, it holds
     * view.title, view.content and view.navigation properties which can be
     * overridden programatically if needed.
     * 
     * @param mav
     *            ModelAndView with template configuration
     * @param request
     *            current {@link HttpServletRequest}
     * @param response
     *            current {@link HttpServletResponse}
     */
    abstract protected void handleRequest(final ModelAndView mav,
            final HttpServletRequest request, final HttpServletResponse response);

}
